"""
The Game file. Contains main program for the game.
$Id: game.py,v 1.12 2004/12/17 09:57:49 krawczyk Exp $

global variables:
static_globals -- Initialiased once on startup
data -- gamedata valid for one game, is initialised in _init

"""

import pygame, random, math
from pygame.locals import *
import computerplayer, config, extras, flocke, mixer, snowball, player

def _load_n_scale_img(name, size):
    img = pygame.image.load(name)
    if img.get_size() != size:
        img = pygame.transform.scale(img, size)
    else:
        print "Image '%s' needed no scaling." % name
    return img

class Static_globals:
    """Global variables (initialised in Init()):
    background_image -- image used for the background
    snowflakes_max -- Maximum number of snowflakes
    """
    def __init__(self):
        game = config.game
        self.background_image = _load_n_scale_img(config.game["background"], config.scrsize).convert()
        self.snowflakes_max = game["snowflakes"]

class Data:
    """Global Game Data:
    framecounter -- Counts the played frames. -1 Before first update!
    players -- List of Players
    playerdisplays -- List of Playerdisplays
    player_minstrength -- Minimum strength (snow???) before able to throw
    player_dead -- which player is dead? Default = None
    statics -- reference to static_globals
    """
    def __init__(self, statics): #Constructor
        GAME=config.game

        self.statics = statics
        self.framecounter = 1
        self.players = [] #List of Players
        self.playerdisplays = [] #Displays for player information
        self.player_minstrength = GAME["player.minstrength"]
        self.player_dead = None
        self.objs_pass = pygame.sprite.RenderUpdates() #Gaming Objects, passive Sprites
        self.objs_act  = pygame.sprite.RenderUpdates() #Gaming Objects, active  Sprites
        self.snowflakes = 0
        self.myclock = pygame.time.Clock()

    def Next_Frame(self):
        self.framecounter += 1 #Increment framecounter
        tick=self.myclock.tick(config.fps)
        if self.framecounter % 100 == 0:
            print self.myclock.get_fps(), self.myclock.get_time(), pygame.time.get_ticks(), tick/100


def Load_Music():
    muzaklist = config.game["music"]
    mixer.mixer.load(random.choice(muzaklist))
    mixer.mixer.play(0) #Einmal abspielen und Event kommt dann

def Init():
    global static_globals
    
    static_globals = Static_globals()
    game=config.game
    config.scr.fill((0,0,128))
    f = pygame.font.SysFont("timesnewroman", 50)
    config.scr.blit(f.render("Initialising Game...", 0, (0, 255, 255)), (0, 0))
    pygame.display.update()

def GameLoop():
    global data

    data.playing = True
    extra_probability = config.extras["probability"]
    snowflakedelay = config.game["snowflake.delay"]
    scr = config.scr
    bgr = data.statics.background_image
    while data.playing and data.framecounter != 0:
        data.Next_Frame()

        #First clean up
        to_update = []
        for i in data.players + data.playerdisplays:
            to_update.extend( i.Erase(scr, bgr) )
        data.objs_pass.clear(scr, bgr)
        data.objs_act.clear(scr, bgr)

        #Update Stuff
        for i in data.players:
            i.Update()
        data.objs_pass.update()
        data.objs_act.update()

        if data.framecounter % snowflakedelay == 0:
	      if data.snowflakes < data.statics.snowflakes_max:
	          data.snowflakes += 1
                  flocke.Flocke(data.objs_pass)
              #extras.Extra_tumbling_Snowball(data.objs_act)
        if random.random() < extra_probability:# *20:
            extra = random.choice(extras.extralist)(data.objs_act)
            #Create a new Extra and add it to the objs

        #Handle Collisions
        Handle_coll(data)
            
        for event in pygame.event.get():
            if event.type == QUIT or (event.type == KEYDOWN and event.key == K_ESCAPE):
                data.playing = False
            #print event
            if event.type == KEYDOWN:
                k = event.key
                for pl in data.players:
                    if pl.Handle_Keys(k, True):
                        break
            elif event.type == KEYUP:
                k = event.key
                for pl in data.players:
                    if pl.Handle_Keys(k, False):
                        break
            elif event.type == USEREVENT:
                #print event
                Load_Music()
            else:
                pass
                #print "Event unknown..."

        #Draw the stuff
        for i in data.players + data.playerdisplays:
            to_update.extend( i.Draw(scr) )
        to_update.extend(data.objs_pass.draw(scr))
        to_update.extend(data.objs_act.draw(scr))

        pygame.display.update(to_update)
        to_update = []
        if data.player_dead != None and data.framecounter > 0:
            print "Player %d killed after %d frames..." % (data.players.index(data.player_dead), data.framecounter)
            data.framecounter = -150
            config.mixer.fadeout(2800)


def Handle_coll(gamedata):
    hitlist = {}
    sprites_2_kill = []
    for pl in gamedata.players: #Check collision with each player
        c = pygame.sprite.spritecollide(pl, gamedata.objs_act, False)
        sprites_2_kill.extend(c)
        hitlist[pl] = c

    do_exit=False
    for pl, c in hitlist.iteritems():
        for i in c:
            if isinstance(i, snowball.Snowball): #Hit by a snowball?
                pl.Hit(i)
            elif isinstance(i, extras.Extra): #Player got an extra
                other_players = [p for p, p_items in hitlist.iteritems() if p_items.count(i) > 0]
                if len(other_players) > 1:
                    pl = random.choice(other_players)
                pl.Extra_Caught(i)
                do_exit=True #Exit all loops
                break
            else:
                print "Player", pl, "collided with", i,"type",type(i)
        if do_exit: break
    for i in sprites_2_kill: #Now kill the sprites
        i.kill()

def _init(no_player):
    """
    no_player -- Number of Players
    """
    global data

    data=Data(static_globals)
    for i in range(0,no_player):
        p = config.player[i]
        p_obj = player.Player(p, data)
        data.players.append(p_obj)
        data.playerdisplays.append(player.PlayerStatus(p_obj, p["displaypos"]))
    if(no_player < 2):
        for i in range(no_player,2):
            p = config.player[i]
            p_obj = computerplayer.ComputerPlayer(p, data)
            data.players.append(p_obj)
            data.playerdisplays.append(player.PlayerStatus(p_obj, p["displaypos"]))
    config.scr.blit(data.statics.background_image, (0, 0) )
    pygame.display.update()
    Load_Music()

def main(no_player):
    """
    Main routine for game.
    no_player -- No of players in this game
    """
    _init(no_player)
    if "interactive" in config.__dict__:
        if config.interactive:
            import code, readline
            code.interact("Leise rieselt der Schnee; interactive Konsole:", raw_input, globals())
    GameLoop()
